This week in Google Developer Live Israel, we show you how to work with Google App script to run Monte Carlo simulations and get the results in an excellent informative way inside Google spreadsheets. We took it further and explained how to run these scripts on your instance machine inside Compute Engine with nodeJS.
This is a powerful option because the ability to ‘try’ quickly on App Script and then take the code to ‘production’ (=more efficient way) on Compute engine gives you more productivity.
So what are we doing?
First, let’s touch on the definition. This problem-solving technique approximates the probability of specific outcomes by running multiple trial runs, called simulations, using random input variables. The remarkable aspect is that we are steering the scenarios by using randomness.The randomness helps us ‘try’ each future strategy in a way that includes our probability per variable. This allows us to fine-tune our trial runs to answer a question with several variables. It will help us find the best way to spend time with our salesperson.
Monte Carlo Simulations Steps
1. Define a model with a domain of possible inputs.
2. Generate input values randomly, sampling from a probability distribution over the domain.
3. Perform a deterministic computation on the inputs.
4. Aggregate the results.
Our Case
What should our sales friend do in the next 50 days?
She can only do 25 big deals that take 2 days per deal or run on 50 small deals that take one day per deal? What is the best blend of big and small deals for her skill sets?
We make few assumptions (of course) like:
- The probability for closing a big deal – Let’s say 30% chance.
- The probability for closing a small deal – Let’s say 50% chance.
- What is the value of each deal. For example: $25K for big deal and $10K for small one.
- The amounts of deals that she can do in X days. For example: a big deal will take two days and a small deal only one day. So if we have 10 days we can do a maximum of five big deals or a maximum of 10 small deals.
All these parameters will drive the results, so you wish to base them as close as possible to reality. The next step, after we define our possible inputs for the problem is to generate inputs randomly and measure the results. In our case, we printed the results back on google sheet and use the charts in order to have a better look on them.
The main usage for App Script in this case is to have a quick ‘look and feel’ for our data. Once, we are happy with this initial phase and we are ready to test 10K (or 10B) scenarios it’s time for us to move our code to Compute Engine.
Here we will have Google’s scale under our hands with the ability to simulate our ‘problems’ on lots of machines without any worries about ‘administrative tasks’ like creating images of our virtual machines and deploying them on 10K machines.
Here is the code that will run this simulation on Node.js inside Compute Engine.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /************************************************* | |
| * This is a simple Monte Carlo simulation to see | |
| * whether we should | |
| * go for X BIG deal and/or Y SMALL deals. | |
| * | |
| * What is the best blend? | |
| * | |
| * Author: Ido Green | plus.google.com/+greenido | |
| * Date: 16 July 2013 | |
| * | |
| * **********************************************/ | |
| // fun with files – so we could have CSV with our results | |
| fs = require("fs"); | |
| // Few Important assumptions that drive the outcome | |
| // | |
| // Number of times to run the simulation | |
| var senarios = 1000; | |
| // % chance of making big deal | |
| var bigDealPerc = 0.3; | |
| // % chance of making a small deal | |
| var smallDealPerc = 0.5; | |
| // Amount of deal const. you can make in X days. | |
| // We gave 'big' deal twice the effort of a small deal. | |
| var amountOfDealsExecution = 50; | |
| var amountBigDeals = 25; | |
| var amountSmallDeals = 50; | |
| // values per deal in $ | |
| var bigDeal = 27000; | |
| var smallDeal = 15000; | |
| // This is the heart of the simulation | |
| // We run X senarios and see what is the best 'blend' of deals | |
| function findMaxAmount() { | |
| var outData = "Amount,Big wins, Big Losses\n"; | |
| var maxAmount = 0; | |
| var maxDeals = 0; | |
| for (var i=0; i < senarios; i++) { | |
| var maxSenario = runSenarioBlending(); | |
| console.log(i + ") Amount: " + maxSenario.moneyWeMade + | |
| " Big Deals: " + | |
| (maxSenario.winsBig + maxSenario.lossBig) ); | |
| if (maxAmount < maxSenario.moneyWeMade) { | |
| maxAmount = maxSenario.moneyWeMade; | |
| maxDeals = maxSenario.winsBig + maxSenario.lossBig; | |
| } | |
| outData += maxSenario.moneyWeMade + "," | |
| + maxSenario.winsBig + "," + maxSenario.lossBig + "\n"; | |
| } | |
| console.log ("== max amount: " + maxAmount + | |
| " deals: "+ maxDeals); | |
| fs.writeFile("x-decisions-node-results.csv", outData); | |
| } | |
| // Running on all the deals' comninations and find the best blend | |
| function runSenarioBlending() { | |
| var maxSenario = new Object(); | |
| var maxAmount = 0; | |
| for (var i=0; i < amountBigDeals; i++) { | |
| var statsObj = runDealsBlending(i+3); | |
| if (statsObj.moneyWeMade > maxAmount) { | |
| maxSenario = statsObj; | |
| maxAmount = statsObj.moneyWeMade; | |
| } | |
| } | |
| return maxSenario; | |
| } | |
| // | |
| // | |
| // | |
| function runDealsBlending(curLine) { | |
| var winsBig = 0; | |
| var lossBig = 0; | |
| var winSmall = 0; | |
| var lossSmall = 0; | |
| var curTrial = 0; | |
| var moneyWeMade = 0; | |
| var retObj = new Object(); | |
| for (var b=0; b < curLine-2; b++) { | |
| if (winBigDeal()) { | |
| // We won this big deal | |
| moneyWeMade += bigDeal; | |
| winsBig++; | |
| } | |
| else { | |
| lossBig++; | |
| } | |
| } | |
| for (var s=0; s < amountSmallDeals && | |
| ((b*2)+s) < amountOfDealsExecution; s++) { | |
| if (winSmallDeal()) { | |
| // won small deal | |
| moneyWeMade += smallDeal; | |
| winSmall++; | |
| } | |
| else { | |
| lossSmall++; | |
| } | |
| } | |
| retObj.winsBig = winsBig; | |
| retObj.winSmall = winSmall; | |
| retObj.lossBig = lossBig; | |
| retObj.lossSmall = lossSmall; | |
| retObj.moneyWeMade = moneyWeMade; | |
| //console.log(winsBig + " , " + winSmall + " , " + lossBig + " , " + lossSmall + " , "+ moneyWeMade + " \n"); | |
| return retObj; | |
| }; | |
| // determines if we win in a given trial when we aim for BIG deal | |
| function winBigDeal() { | |
| if (Math.random() < bigDealPerc) { | |
| return true; | |
| } | |
| return false; | |
| }; | |
| // determines if we win in a given trials when we aim for small deal | |
| function winSmallDeal() { | |
| if (Math.random() < smallDealPerc) { | |
| return true; | |
| } | |
| return false; | |
| }; | |
| /***************************** | |
| * | |
| * Start the Simulation | |
| * | |
| ******************************/ | |
| var startTime = Date.now(); | |
| findMaxAmount(); | |
| var endTime = Date.now(); | |
| console.log("\n===== Took us: " + (endTime – startTime) + " milliseconds"); |
Discover more from Ido Green
Subscribe to get the latest posts sent to your email.

Ido: Great presentation on Monte Carlo simulations. You have a very cool Google App Script demo at the very beginning of the video. Can you provide that Google App Script code? Thanks.
Thank you.